package com.gitee.sparta.core.cluster.netty.handler;

import com.gitee.sparta.core.bean.cluster.ClusterCmd;
import com.gitee.sparta.core.bean.cluster.ClusterProtocol;
import com.gitee.sparta.core.cluster.AbstractClusterLeader;
import com.gitee.sparta.core.cluster.ClusterCache;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 *      leader 的心跳检测
 * </p>
 *
 * @author zyred
 * @since v 0.0.2
 */
@Slf4j
@ChannelHandler.Sharable
public class NettyHeartbeatHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

        if (!(evt instanceof IdleStateEvent)) {
            super.userEventTriggered(ctx, evt);
            return;
        }

        IdleStateEvent idle = (IdleStateEvent) evt;
        // 读空闲，这里只有 leader 才会触发读空闲
        if (idle.state() == IdleState.READER_IDLE) {
            final Integer sid = ClusterCache.getSid(ctx.channel());
            // 发送 ping
            AbstractClusterLeader.sendQueue(
                    new ClusterProtocol(ClusterCmd.PING, sid, 0, ctx.channel())
            );
        }

        // 写空闲，这里只有 follower 才会触发
        else if (idle.state() == IdleState.WRITER_IDLE) {
            final Integer sid = ClusterCache.getServerId();
            ctx.channel().writeAndFlush(
                    new ClusterProtocol(ClusterCmd.HEARTBEAT, sid, 0)
            );
        }

        // 其他不处理
        else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
